package mathy.wili.extract_srcFile.java;
import java.io.Serializable;
import java.lang.reflect.Field;
import mathy.c.Ca;
import mathy.wili.autoeq.Refs;
import mathy.wili.c.Class9;
/**
 * 
 * @author weila 2021年2月23日
 */
public class FieldRange extends ClsMemberRange {
	private static final long serialVersionUID = 1L;

	public final String name;

	/**
	 *  Set this because: may defined more than one field. eg. int a=2, b="".length;
	 */
	public final int fieldsStart;

	/**
	 * eg. "public int" in "public int age;"
	 */
	public final String head;

	public FieldRange[] ranges;

	/**
	 * 	直接简单值
	 */
	public boolean isStaticFinalSimpleValue;

	/**
	 * 	若属性有初始常量值 cls.field
	 */
	public final ClsAndField referedStaticFinalField;

	transient Field field;
	public String toString() {
		if ("".isEmpty())
			return this.head + " " + root.fileSt0.substring(this.aStart, this.aEnd);
		return super.toString() + ", nam=" + name;
	}

	public int getLastLineNo() {
		if (lastLineNo >= 0)
			return lastLineNo;
		return lastLineNo = this.root.lineNoAt(this.aEnd);
	}
	public class ClsAndField implements Serializable {
		private static final long serialVersionUID = 1L;

		//字段或有初始常量值 cls.field
		public Class<?> cls;

		public String fname;

		transient Field field;
		public String toString() {
			return cls.getSimpleName() + "." + fname;
		}

		public ClsAndField(String clsSimpleName, String field) {
			Class<?> ret = FieldRange.this.root.classOfName(clsSimpleName);
			this.cls = ret;
			this.fname = field;
		}

		public Field getField() {
			if (field == null) {
				field = Class9.getDeclaredField(fname, cls);
			}
			return field;
		}
	}
	public String toSource() {
		String ret = this.head + " " + root.fileSt0.substring(this.aStart, this.aEnd);
		return ret;
	}

	public Field get() {
		if (field != null)
			return field;
		try {
			this.field = this.clsRange.cls.getDeclaredField(this.name);
			return field;
		} catch (Exception e) {
			return null;
		}
	}

	public void setVisited() {
		if (name.equals("UseLog"))
			if (int.class.equals(this.get().getDeclaringClass()))
				Refs.visitAtt();
		super.setVisited();
		if (ranges != null) {
			for (FieldRange ele : ranges)
				ele.visited = true;
		}
	}

	//static final Pattern notConst = Pattern.compile("[\\w\\.]+");
	public FieldRange(RootOfClsMember root, String head, String name, int fieldsStart, int start, int end) {
		super(root, start, end);
		this.head = head;
		this.fieldsStart = fieldsStart;
		if (fieldsStart < start)
			Ca.pause();
		int ind = name.indexOf('[');
		if (ind != -1) {
			name = name.substring(0, ind);
		}
		String valueSrc = root.fileSt.substring(start, end);
		int ind2 = valueSrc.indexOf('=');
		this.name = name;
		if (root.curClsRange != null)
			root.curClsRange.addField(this);
		boolean referedStaticFinal = false;
		{//若赋值表达式所在字段是否静态常量简单值，设置this.constField
			Refs.key();
			ClsAndField cf = null;
			//eg. static int UseLog = Logv.Log1, 当设立条件：提取UseLog时，必需Logv.log1,因Log1或是静常量
			if ("".isEmpty() || this.name.equals("LogLevel")) {
				String defineSt = this.toSource();
				ind = defineSt.lastIndexOf('=');
				String nameValue = defineSt.substring(ind + 1).trim();
				if (nameValue.endsWith(";")) {
					nameValue = nameValue.substring(0, nameValue.length() - 1);
				}
				ind2 = nameValue.lastIndexOf('.');
				if (nameValue.matches("[^\\d]\\w*\\.[^\\d]\\w*")) {
					//eg. int att=Level.num
					String cname = nameValue.substring(0, ind2), fname = nameValue.substring(ind2 + 1);
					cf = this.new ClsAndField(cname, fname);
					if (cf.cls == null) {
						cf = null;
					} else if (!cf.fname.equals("class") && Class9.isStaticFinalSimpleValue(cf.cls, cf.getField())) {
						StaticFinalSimpleValue_fieldCheck.getInst__(false);
						referedStaticFinal = true;
					} else {
						cf = null;
					}
				} else if (nameValue.matches("\\d+[\\d\\.]*|true|false")) {
					referedStaticFinal = true;//eg. int aa=5;
				} else if (nameValue.matches("['\"][^'\"]*[\"']")) {//预期串中只有空白，故此正则式可靠
					referedStaticFinal = true;//eg. String aa="asdf";
				}
			}
			this.referedStaticFinalField = cf;
		}
		{//判断本字段是否静态常量简单值
			boolean i_am_staticFinal = Class9.isStaticFinalSimpleValue(this.get().getDeclaringClass(), this.get());
			this.isStaticFinalSimpleValue = i_am_staticFinal && referedStaticFinal;
		}
	}

	public static FieldRange getInstBy(Field fd) {
		Class<?> cls = fd.getDeclaringClass();
		RangesOfClsMember memRange = RangesOfClsMember.getInst(-1, cls);
		if (memRange == null)
			return null;
		ClsRange crange = memRange.getClsRange(cls);
		if (crange == null && Refs.NULL())
			return null;
		return crange.fieldMap.get(fd.getName());
	}
}